package localSearch;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Logger;
import random.TestClusterBuilder;
import util.GAConfig;
import util.GAOperationsConfig;
import util.Filter;
import instrumentation.Condition;
import instrumentation.ConditionIf;
import instrumentation.ConditionSwitch;
import instrumentation.CoverageBranchTarget;
import instrumentation.Data;
import instrumentation.TrackerCoverage;
import GA.*;
import Operations.*;
import ReadWriteFieldsRelations.*;

public class HillClimbing extends LocalSearchPopulation{
	private static final Logger logger = Logger.getLogger("MAMDA.LocalSearch");

	private  TrackerCoverage tracker;
	private  long startTime;
	private  long elapsed;
	private  long TestTimeout;
	private Map<Integer, Map<Class<?>, List<String>>>  recommendMethods = new LinkedHashMap<Integer, Map<Class<?>, List<String>>>();

	@Override	
	public Chromosome execute()throws  IOException, ClassNotFoundException{
		startTime=gaInfo.getStartTime();
		TestTimeout=gaInfo.getTestTimeOut();
		elapsed = (Calendar.getInstance().getTimeInMillis() - startTime);
		 LocalSearch HillClimbing = GAOperationsConfig.getLocalSearch();

		tracker = TrackerCoverage.getTracker();
//		for(int j=1;j<1000;j+=2){
//	//		if(j<=1 || j>=99) continue;
//	//		if(j!=250)continue;
//							recommendMethods= calculateMethodsRecommend(j,gaInfo);
//							HillClimbing.displayConditionAndRecommendMethods(recommendMethods,this.getCondition(j),j);
//		}

		int trgtBranch=getTargetToCover(tracker);
		if(trgtBranch==-1) return null;
		Chromosome chrom =tracker.branchNotCoveredByIndividual.get(trgtBranch);
	//	if(chrom==null) return null;
	   System.out.println("Branch# :" + trgtBranch );//+ " Original chrom: "+chrom.toString() );
	   if(trgtBranch==47||trgtBranch==48)
		   	System.out.print(" execute: " +trgtBranch);
	     recommendMethods= calculateMethodsRecommend(trgtBranch,gaInfo);
// Display  the targeted branches and the recommended methods
		 HillClimbing.displayConditionAndRecommendMethods(recommendMethods,this.getCondition(trgtBranch),trgtBranch);
			Chromosome result = hillClimb(chrom,trgtBranch,recommendMethods);
			if(result!=null)
				return result;

		return null;
	}

	public int getTargetToCover(TrackerCoverage tracker)throws  IOException, ClassNotFoundException{
		int trgtBR=-1;
		Map<Integer,CoverageBranchTarget> trackers=tracker.getTrackers();
		List<Integer> keys = new ArrayList<Integer>(trackers.keySet());
			CoverageBranchTarget condTrgt=null;
		int times=0;
		while(trgtBR==-1){
			times++;
			for ( int indx = 0; indx < trackers.size(); indx++) {
				if(tracker.branchNotCoveredByIndividual.containsKey(keys.get(indx))){ 
					condTrgt = (CoverageBranchTarget) trackers.get(keys.get(indx));
					if(condTrgt.getQuality()==Float.NEGATIVE_INFINITY){
						tracker.branchNotCoveredByIndividual.remove(keys.get(indx));
						continue;
					}
					Condition c =this.getCondition(keys.get(indx));
					if(c.getIsCallMethod()&&times!=2) continue;
					if(condTrgt==null) continue;
					int considerBr=	keys.get(indx);
					if( condTrgt.getAttempt()!=gaInfo.getAttempt()){
						trgtBR=considerBr;

						break;
					}

			}
			}//for indx
			if(tracker.branchNotCoveredByIndividual.size()==0)
				return -1;
			if(trgtBR==-1)
				gaInfo.setAttempt(gaInfo.getAttempt()+1);
			else{
				condTrgt = (CoverageBranchTarget) trackers.get(trgtBR);
				condTrgt.setAttempt(gaInfo.getAttempt());
			}
		}
			return trgtBR;
	
	}
	private Condition getCondition(int trgtBR){
		Map<Integer, Condition> mapBranchCondition=gaInfo.getMapBranchCondition();
	       TreeMap<Integer,Condition> sorted_map = new TreeMap<Integer,Condition>(mapBranchCondition);
	       if(sorted_map.containsKey(trgtBR)){
	   			Condition c= sorted_map.get(trgtBR);
	   			return c;
	       }
		return null;
	}
	private Data getDataCondition(int trgtBR,int value){
		Map<Integer, Condition> mapBranchCondition=gaInfo.getMapBranchCondition();
	       TreeMap<Integer,Condition> sorted_map = new TreeMap<Integer,Condition>(mapBranchCondition);
	       if(sorted_map.containsKey(trgtBR)){
	   			Condition c= sorted_map.get(trgtBR);
					if(value==1){
						if(c.getV1() instanceof Data)
							return (Data) c.getV1();
					}
					if(value==2){
						if(c.getV2() instanceof Data)
							return (Data) c.getV2();
					}
				}

		
		return null;
	}
	private static final int ITERATIONS = 500;
	/** Number of attempts when a method is selected */
	private final int TTL_FIRST = 10;
	/** Number of attempts for operations able to reduce the branch distance */
	private final int TTL_IMPROVEMENT  = 20;
	public Chromosome hillClimb (Chromosome originalIndividual,int trgtBR,Map<Integer, Map<Class<?>, List<String>>>  methodsRecommendPValues){
		
		int ttl = 0;//how many times that a position/ method can be targeted again
		Map<Integer,CoverageBranchTarget> trackers=tracker.getTrackers();
		CoverageBranchTarget condTarget = (CoverageBranchTarget) trackers.get(trgtBR);
		if(condTarget==null) return null;
		float oldBranchDistFitness=condTarget.getQuality();		
		Chromosome individualMuted=null;
		for (int i = 0; i < ITERATIONS && elapsed < TestTimeout && this.gaInfo.getNoExecution()<=GAConfig.fitnessEvaluation; i++) {
		if(--ttl < 0) {
			individualMuted=originalIndividual.clone();	
			ttl = TTL_FIRST;
		}

//		System.out.println("\t originalIndividual. : "+ originalIndividual.toString() +" " + " fit: "+ originalIndividual.getFitness() + " BRdist: "+ originalIndividual.getBranchDistance());

		// the mutate operations must change the size of the individual, except in the modify operations that returns the same size of the indiviuals with the original
			boolean canContinue = true;
			while(canContinue && individualMuted.getSize()==originalIndividual.getSize())
				canContinue=mutate(individualMuted,trgtBR);
//	if(trgtBR==41)
//		System.out.println("\t muteted. : "+ individualMuted.toString() +" " + " fit: "+ individualMuted.getFitness() + " BRdist: "+ individualMuted.getBranchDistance());



			tracker.reset();
			ReflectionExecutor.execute( gaInfo,individualMuted);


			tracker.calculateFitness(individualMuted);
//			if(trgtBR==41){
//					System.out.println("\t originalIndividual. : "+ originalIndividual +" " + " fit: "+ originalIndividual.getFitness() + " BRdist: "+ originalIndividual.getBranchDistance());
//
//				System.out.println("\t muteted. : "+ individualMuted +" " + " fit: "+ individualMuted.getFitness() + " BRdist: "+ individualMuted.getBranchDistance());
//			}
			

			if(condTarget.getQuality() == Float.NEGATIVE_INFINITY) {
				logger.info("Target " + condTarget.toString() + " hit");
					return individualMuted;
		}
			if(condTarget.getQuality() == Float.NEGATIVE_INFINITY) {
				logger.info("Target " + condTarget.toString() + " hit");
					return individualMuted;
		}
		
			if(oldBranchDistFitness==condTarget.getQuality())
				ttl = 0;
			else{
					ttl = TTL_IMPROVEMENT;
					oldBranchDistFitness=condTarget.getQuality();
					originalIndividual=individualMuted.clone();
					originalIndividual.setBranchDistance(individualMuted.getBranchDistance());
					originalIndividual.setFitness(individualMuted.getFitness());
					Chromosome chrom =tracker.branchNotCoveredByIndividual.get(trgtBR);
					if(chrom.getBranchDistance()>condTarget.getQuality()){ // Stack example!
						chrom=originalIndividual.clone();
						chrom.setBranchDistance(originalIndividual.getBranchDistance());
						chrom.setFitness(originalIndividual.getFitness());
						
						tracker.branchNotCoveredByIndividual.put(trgtBR,chrom);
					}
				}
			 elapsed = (Calendar.getInstance().getTimeInMillis() - startTime);
//			   if(trgtBR==39)


		}
		return null;
	}

	public Map<Integer, Map<Class<?>, List<String>>> calculateMethodsRecommend(int trgtBR,GAInfo gaInfo) {
		List<String> methodsList = new LinkedList<String>();
		Map<Integer, Map<Class<?>, List<String>>>  methodsRecommendValue = new LinkedHashMap<Integer, Map<Class<?>, List<String>>>();
		Map<Class<?>, List<String>> methodsRecommend = new LinkedHashMap<Class<?>, List<String>>();
		MethodRelations relations = gaInfo.getMethodRelations();
		Condition c=this.getCondition(trgtBR);// sorted_map.get(trgtBR);
		Data v1=null;


						 v1=this.getDataCondition(trgtBR,1);
						 if(v1!=null){
								if(v1.isField()){						
									Map<Class<?>, Map<String, List<String>>> writeFieldMethods = relations.buildWriteFiledMethodDependence();
									for(Class<?> clazz:writeFieldMethods.keySet()){
										Map<String, List<String>> mWriteFields = writeFieldMethods.get(clazz);
										methodsList = mWriteFields.get(v1.getFieldName());
										if(methodsList!=null)
											methodsRecommend.put(clazz, methodsList);
									}
								}
						}

				if(methodsRecommend.size()==0&&v1!=null){ 
					methodsRecommend=relations.getWriteMethods(c.getCName(),c.getMName());
			    }
				if(methodsRecommend.size()==0&&v1!=null){ 
					methodsRecommend=relations.getAllWriteMethods(c.getCName());
			    }
	
//Add the public method name that contains the target
		List<String>	recMethodList = new LinkedList<String>();
			Condition condition =this.getCondition(trgtBR);
		       Map<String, Class<?>> cluster= gaInfo.getTestCluster().getCluster();
		       Class<?> clazzMethodTarget=cluster.get(condition.getCName());

			if(!condition.getIsPrivate()){
				recMethodList=methodsRecommend.get(clazzMethodTarget);
				if(recMethodList==null)
					recMethodList = new LinkedList<String>();
				if(recMethodList.size()!=0){
					if(!recMethodList.contains(condition.getMName()))
							recMethodList.add(condition.getMName());
					
				}else{
					recMethodList.add(condition.getMName());
				}
				methodsRecommend.put(clazzMethodTarget, recMethodList);

			}

//			if(v1!=null &&methodsRecommend.size()!=0 )
				methodsRecommendValue.put(1, methodsRecommend);

			
					
		return methodsRecommendValue;
	}
	/** probability to add an operation(s)  */
	private float probAdd = 0.5f;

	/** probability to remove  an operation(s) */
	private float probRemove = 0.2f;

	/**   probability to modify the parameters of  an operation(s)*/
	private float probModify = 0.3f;



	public boolean mutate(Chromosome individual,int trgtBR){
		List<Operation> ops = individual.getTest();
		
		final boolean isModifiable = ops.size() >= 0 ;// && this.isPredicateTypePrimitive(trgtBR);

		final boolean isRemovable = ops.size()>3;

		int choice;
		/** 0 => add; 1 => modify; 2 => remove */
		if(isModifiable && isRemovable) {
			float c = ValuesGenerator.getRandomFloat() * (probAdd + probModify + probRemove);
			if(c < probAdd) choice = 0;
			else if(c < probAdd + probModify) choice = 1;
			else choice = 2;
		} else if(isModifiable) {
			float c = ValuesGenerator.getRandomFloat() * (probAdd + probModify);
			if(c < probAdd) choice = 0;
			else choice = 1;
		} else if(isRemovable) {
			float c = ValuesGenerator.getRandomFloat()* (probAdd + probRemove);
			if(c < probAdd) choice = 0;
			else choice = 2;
		} else choice = 0;
		
		choice=0;
		if(choice==0){
//			System.out.println("add operation");
			addOperations(individual,trgtBR);
			return true;
		}else if(choice==1){
	//		System.err.println("modify operation ");
			modifyOperations(individual,trgtBR);
			return false;
		}else if(choice==2){
	//		System.out.println("remove operation");
			int pe=individual.getSize();
//			System.out.println("1- remove operation "+individual.getSize() );
			removeOperations(individual,trgtBR);
//			System.out.println("2-remove operation "+individual.getSize() );
			if(pe<individual.getSize()){
				System.err.println("remove operation pe<individual.getSize");
				System.exit(1);
			}
			return true;
		}else{
			System.err.println("HillCimbing.mutate: undefined operation");
		}
		return true;
	}
	private void addOperations(Chromosome individual, int trgtBR) {
//		if(trgtBR==28||trgtBR==28)
//			System.out.print("");
			Map<Integer, Map<Class<?>, List<String>>>  methodsRecommendPValues=this.getRecommendMethods();

			List<Operation> ops = individual.getTest();
		
		int randPos=ValuesGenerator.getRandomIntBetween(0,ops.size()-1);
		int numberMethodsAdded=10 + gaInfo.getAttempt();
		int num = ValuesGenerator.getRandomIntBetween(1,numberMethodsAdded);
		ops = individual.getTest();
		List<Operation> rep = new LinkedList<Operation>();
		rep.addAll(ops.subList(0, randPos));

		for (int i = 0; i < num; i++) {
			Operation newOp=null;
			 newOp=	Operation.recommendedGenerate(gaInfo.getTestCluster(),methodsRecommendPValues);
			if(newOp!=null)
					rep.add(newOp);
			else
					continue;
			}
			rep.addAll(ops.subList(randPos, ops.size()));
			individual.setTest(rep);   	    
		
			if(ValuesGenerator.getBoleean(0.8f)&&GAConfig.useConstantSeeding)
					modifyOperations(individual,trgtBR);
	}

		


	private void removeOperations(Chromosome individual, int trgtBR) {
		Map<Integer, Map<Class<?>, List<String>>>  methodsRecommendPValues=this.getRecommendMethods();
		for (int v = 1; v <= 1; v++) {

			Map<Class<?>, List<String>> recClassMethodToTest = methodsRecommendPValues.get(v);
	
			if (recClassMethodToTest == null)
				continue;
			
			List<Operation> ops = individual.getTest();

			List<Class<?>> keys = new ArrayList<Class<?>>(recClassMethodToTest.keySet());
			int randClass = ValuesGenerator.getRandomInt(recClassMethodToTest.size());
			Class<?> cName = (Class<?>) keys.get(randClass);
			List<String> methodsRecommendedList=recClassMethodToTest.get(cName);
			if(methodsRecommendedList.size()==0)
				System.err.println("Hillclimbing.removeOperations: There are no method to recommend!");
			// choose a writing method to delete!
			int randMethod = ValuesGenerator.getRandomInt(methodsRecommendedList.size());
			String mName=methodsRecommendedList.get(randMethod);
	//		methodsRecommendedList.remove(mName);
			//methodsRecommendedList(Collections.singleton(mName));
			List<String> methodList= new LinkedList<String>();
			methodList.addAll(methodsRecommendedList);
			methodList.removeAll(Collections.singleton(mName));
			// method call that contains the target branch if it is a public
			Condition condition =this.getCondition(trgtBR);
			if(!condition.getIsPrivate()) 
				methodList.add(condition.getMName());

			List<Operation> newOps = new LinkedList<Operation>();
	
			//remove operations from the individual
			int num = ValuesGenerator.getRandomInt(10);
//			for(int i = 0; i < num; i++){
				for(Operation op : ops) {
					if (op instanceof CreateObject){
						 if(methodList.contains("<init>"))
							 	newOps.add(op);
					}
					else if(op instanceof Invoke){
							Invoke m=(Invoke)op;
							 MethodDeclared method = m.getMethod();
							 if(methodList.contains(method.getName()))
									 	newOps.add(op);			 
						 }
				}

			if(newOps.size()!=0){
				ops.clear();
				ops.addAll(newOps);
			}

		}
	

		
	}
	

	private void modifyOperations(Chromosome individual, int trgtBR) {
		Map<Integer, Map<Class<?>, List<String>>>  methodsRecommendPValues=this.getRecommendMethods();
		Map<Class<?>, List<String>> remommenedeClassMethods=methodsRecommendPValues.get(1);
		Condition condition =this.getCondition(trgtBR);
	 	Data v1=null;
        String pValue_v1=null;
        String pType_v1=null;
        int v1_indx=-1;
        Data v2=null;
	    String pValue_v2=null;
	    String pType_v2=null;
	    int v2_indx=-1;
	    String callee_1=null;
	    String callee_2=null;
			if(condition.getV1() instanceof Data){
				 v1=(Data) condition.getV1();
				if(v1.isField()){
					pType_v1=v1.getType();
					callee_1=condition.getCallee1();
				}
				else if(v1.getIndxParam()!=-1){
						pType_v1=v1.getType();
						v1_indx=v1.getIndxParam();
				}
				if(condition.getV1() instanceof instrumentation.Constant){
					pValue_v1=condition.getV2().toString();
				}else if(condition.getV1() instanceof instrumentation.ConstantString){
							pValue_v1=condition.getV1().toString();
						}

			}
				if(condition.getV2() instanceof Data){
					 v2=(Data) condition.getV2();
					if(v2.isField()){
						pType_v2=v2.getType();
						callee_2=condition.getCallee2();
					}else if(v2.getIndxParam()!=-1){
							pType_v2=v2.getType();
							v2_indx=v2.getIndxParam();
					}
				}
			if(condition.getV2() instanceof instrumentation.Constant){
				pValue_v2=condition.getV2().toString();
			}else if(condition.getV2() instanceof instrumentation.ConstantString){
						pValue_v2=condition.getV2().toString();
					}
			if(condition instanceof ConditionSwitch ){
				pValue_v2=""+((ConditionSwitch) condition).getCases().get(trgtBR);
			}
			if(!GAConfig.useConstantSeeding){
				pValue_v2=null;
			}
		//Get Methods name that contains the target branch
	       Map<String, Class<?>> cluster= gaInfo.getTestCluster().getCluster();
	       Class<?> clazzRecomm=cluster.get(condition.getCName());
	       List<String> mRecommend = new LinkedList<String>();
		List<Operation> ops = individual.getTest();
		for(Operation op : ops) {
			if (op instanceof CreateObject){
				CreateObject cObj= (CreateObject)op;
				clazzRecomm= cObj.getConstructor().getClazz();
				 if(!remommenedeClassMethods.containsKey( clazzRecomm)) continue;
				 mRecommend=remommenedeClassMethods.get( cObj.getConstructor().getClazz());
				 if(mRecommend.contains("<init>"))
						 	op= this.modifyConstructorParams( op, clazzRecomm,pType_v1,pValue_v2,v1_indx);
				  }
			else if(op instanceof Invoke){
					Invoke m=(Invoke)op;
					MethodDeclared method = m.getMethod();
					clazzRecomm= method.getClazz();
					 if(!remommenedeClassMethods.containsKey( clazzRecomm)) continue;
					 mRecommend=remommenedeClassMethods.get(method.getClazz());

					 if(mRecommend.contains(method.getName())) {
						 op= this.modifyMethodParams( op, clazzRecomm,pType_v1,pValue_v2,v1_indx); 
					 }
				 }
		}
	}
	private Operation modifyConstructorParams(Operation op,Class<?> clazzRecomm,String pType_v1,String pValue_v2,int v1_indx ){
		 Map<String, Class<?>> cluster = gaInfo.getTestCluster().getCluster();
//		String suggestedValue=this.getPredicateValue(trgtBR);
		 CreateObject cObj= (CreateObject)op;
		ConstructorDeclared cut = cObj.getConstructor();
		if(cut.getClazz()!=clazzRecomm) return op;
		Class<?>[] paramsType = cut.getParameterTypes();
		Object[] actualParams = new Object[cut.getParameterTypes().length];
		String[] p = cut.getParams();
        for (int k = 0; k < actualParams.length; k++) {
                if (Filter.isPrimitiveOrStringType(paramsType[k])){
                    String paramType=Filter.PrimitiveGenericConverter(paramsType[k].getName());
                	String randomValue=ValuesGenerator.buildValue(paramType);
                    p[k] =  ValuesGenerator.modifyActualValue(p[k],randomValue,paramType);
                    if(pType_v1==null) continue;
                     pType_v1=Filter.PrimitiveGenericConverter(pType_v1);


                             if(paramType.equals(pType_v1)&&ValuesGenerator.getBoleean(0.9f)){
                            	 	String pSuggestValue=ValuesGenerator.modifyActualValue(p[k],pValue_v2,pType_v1);
                            	 	p[k]=pSuggestValue;
                         }
                }
        }
        
        cut.setParams(p);

		return op;
	}
	private Operation modifyMethodParams(Operation op,Class<?> clazzRecomm,String pType_v1,String pValue_v2,int v1_indx ){
		 Map<String, Class<?>> cluster = gaInfo.getTestCluster().getCluster();
	     Map<String, String[]>  refFactory=gaInfo.getTestCluster().getRefFactory();

        Invoke invoke=(Invoke) op;
        MethodDeclared method =invoke.getMethod();
        Class<?> clazz=method.getClazz();
        if(!clazzRecomm.equals(clazz))return op;
        final Class<?>[] paramsType = method.getParameterTypes();
        String[] p =invoke.getParams();

        
        for(int i = 0; i < p.length; i++){
            if(Filter.isPrimitiveOrStringType( paramsType[i])){
                String paramType=Filter.PrimitiveGenericConverter(paramsType[i].getName());
            	String randomValue=ValuesGenerator.buildValue(paramType);
                p[i] =  ValuesGenerator.modifyActualValue(p[i],randomValue,paramType);
                if(pType_v1==null) continue;
                pType_v1=Filter.PrimitiveGenericConverter(pType_v1);
  
                    if(paramType.equals(pType_v1)&& ValuesGenerator.getBoleean(0.9f)){
                         String pSuggestValue=ValuesGenerator.modifyActualValue(p[i],pValue_v2,pType_v1);
                         p[i]=pSuggestValue;
                    }
                    if((paramType.equals("java.lang.String")&&pType_v1.equals("java.lang.Character"))&&ValuesGenerator.getBoleean(0.9f)){
                        String pSuggestValue=ValuesGenerator.modifyActualValue(p[i],pValue_v2,paramType);
                        p[i]=pSuggestValue;
                    }
            }
        }

		return op;
	}
	public Map<Integer, Map<Class<?>, List<String>>>  getRecommendMethods(){
		return recommendMethods;
	}
	private static void simpleTestExecute(GAInfo     gaInfo,TestClusterBuilder TestCluster){
		  TrackerCoverage track=  TrackerCoverage.getTracker();

			Chromosome individual=ChromosomeFormer.buildNewChromosome(TestCluster);
			System.out.println(individual.toString());
			
			ReflectionExecutor.execute(gaInfo,individual);
			track.calculateFitness(individual);

//			System.out.println("------------------------");
//			System.out.println(track.toString());
	
	}

	public static void main(String[] args) throws ClassNotFoundException,IOException{
		GAInfo     gaInfo     = new GAInfo();

		long startTime = Calendar.getInstance().getTimeInMillis();
		long elapsed = Calendar.getInstance().getTimeInMillis() - startTime;
		gaInfo.setTestTimeOut( 60 * 1000*10);
		gaInfo.setStartTime(startTime);

		ValuesGenerator.resetSeed(20);	      


		GAConfig.setAlgorithmName("Memetic Algorithm");
		
		 Set<Class<?>> allClasses = new LinkedHashSet<Class<?>>();
			System.out.println("CUT is:" + GAConfig.classFilePath);
			
		      allClasses.addAll(TestClusterBuilder.readClassFromFile());
		      Set<Class<?>> classesToTest = TestClusterBuilder.filterUntestableClasses(allClasses);

				// calculate the test cluster and the set of types involved in the
				TestClusterBuilder TestCluster = new TestClusterBuilder(classesToTest);		
		
		      gaInfo.setTestCluster(TestCluster);
		      ////////////////////////
		      MethodRelations relations = new MethodRelations(allClasses);
		      relations.buildRelations();
		      gaInfo.setMethodRelations(relations);
			      
		LocalSearch HillClimbing = GAOperationsConfig.getLocalSearch();
	      gaInfo.setMapBranchCondition(HillClimbing.readFileWGZ(gaInfo.getTestCluster()));
	      HillClimbing.setExtraInfo(gaInfo);
		

		try {
			for(int j=0;j<1;j++){
				simpleTestExecute(gaInfo, TestCluster);
			}
				TrackerCoverage tracker = TrackerCoverage.getTracker();
				int no=tracker.branchNotCoveredByIndividual.size();
				for (int i = 0; i <=no -1;i++){
//				for (int i = 0; i <20 ;i++){
					Chromosome improvedIndividual =HillClimbing.execute();
				}
				System.out.println("------------------------");
				System.out.println(tracker.toString());

		//}
				System.exit(0);
				
		} catch (Throwable e) {
			System.err.println("chromFormer.main: " + e);
			System.exit(1);
		}
	}

}